namespace CCStatisticsTDD
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using CCStatistics.Domain.Api;
    using CCStatistics.Domain.Api.Interfaces;

    using NUnit.Framework;

    using Rhino.Mocks;

    using TDDViewOutputStatus;

    using ThoughtWorks.CruiseControl.Core;
    using ThoughtWorks.CruiseControl.Core.Publishers.Statistics;

    /// <summary>
    /// This is a monolitic 'Smoke Test'. There are many fine grained tests to be writtem!
    /// </summary>
    [TestFixture]
    public class MainTestFixtureBaselineSmokes : AssertionHelper
    {


        private static List<string> GetMockList(string mockBuildName, int repositoryBuildCount)
        {
            // Add the build name to the array tht is expected to be available for ALL builds
            // from the repositoy. Here we use 10


            return
                Enumerable.Repeat(mockBuildName + " {0}", repositoryBuildCount).Select(
                    s => String.Format(s, DateTime.Today.ToLongTimeString())).ToList();



        }

        private static string DefaultDirectory
        {
            get { return Environment.GetEnvironmentVariable("TEMP"); }
        }

        /// <summary>
        /// NOTE: This is a FULL CYCLE Mock Smoke test. We need many more finely grained
        /// tests. This is just to ensure all is well in the application. Each subcomponent 
        /// will need to have tests added as this evolves. In the mean time this works
        /// well to ensure we fundamentally work and this is called from OUR BuildServer 
        /// (how META is that?) to ensure this is working.
        /// This should be your first stop to undersand this code
        /// </summary>
        [Test]
        public void ShouldSmokeTestProjectAPI()
        {
            // We need a name for this project
            const String mockBuildName = "CCStatisticsBuildMock";


            // Simulate 100 legacy build results
            const int repositoryBuildCount = 100;

            ICCStatsView _view = new MockTDDView();

            // We need to create a mock for a basic single CruiseControl project using the provided interface
            // In the application we get a project by it being selected from the UI and finding it in the
            // list of projects gathered from the config file.

            var cruiseControlProject = GetCruiseControlProject(mockBuildName, repositoryBuildCount);


            // OK now it's interesting.. We have our own ICCStatisticsPublisher which is a stand-in for the
            // StattisticsPublisher concrete class in CruiseControl. We need to add a new overload 
            // and obviously make this behave in ways it was not intended to (as we are doing all the legacy builds)
            var _statisticsPublisher = MockRepository.GenerateMock<ICCStatisticsPublisher>();

            // Here we use the mock array of stats created above.
            _statisticsPublisher.Expect(x => x.ActiveStatistics).Return(MockStats).Repeat.Any();

            // here we Expect ProcessLogFile to be called .Repeat.Times(repositoryBuildCount), but we want a different return value each time (the next build label expected)...
            for (var i=1; i <= repositoryBuildCount; i++)
                _statisticsPublisher.Expect(x => x.ProcessLogFile(null, null, 0)).IgnoreArguments().Return(i+1);

            // OK go create a real concreete object with all the mcok scaffolding
            //var _ProjectStatisticsPresenter = mocks.PartialMock<ProjectStatisticsPresenter>(_view, cruiseControlProject, _statisticsPublisher, DefaultDirectory);
            var _ProjectStatisticsPresenter = new ProjectStatisticsPresenter(_view, cruiseControlProject, _statisticsPublisher, DefaultDirectory);


            //_ProjectStatisticsPresenter.Expect(
           //     x => x.ProcessLogFile(null, null)).IgnoreArguments().Repeat.Times(repositoryBuildCount);
          // Run the unit test
            _ProjectStatisticsPresenter.RecalculateStatistics();

            

       }

        private static List<Statistic> MockStats
        {
            get
            {
                return
                    new List<Statistic>(new[] {new Statistic("AssemblyDependencyRatio","//builditem[@AssemblyDependencyRatio]")});
            }

        }

        private static IProject GetCruiseControlProject(string mockBuildName, int repositoryBuildCount)
        {
            // Create the repository mock
            var repository = MockRepository.GenerateStub<IIntegrationRepository>();
            var buildNames = GetMockList(mockBuildName, repositoryBuildCount);

            // OK set this up to return our builds
            repository.Stub(x => x.GetBuildNames()).Return(buildNames.ToArray()); //x.GetBuildNames().Equals(buildNames)); //.Will(Return.Value(buildNames));

            var currentProject = MockRepository.GenerateStub<IProject>();
            // Finally, add this mock to our project and we are ready for the next step
            currentProject.Stub(x => x.IntegrationRepository).Return(repository).Repeat.Any();

            // This app obviously needs to know about where all those nice XML Build files are sitting
            // here we just return a temp directory via the helper method
            currentProject.Stub(x => x.Name).Return(mockBuildName).Repeat.Any();
            currentProject.Stub(x => x.ArtifactDirectory).Return(DefaultDirectory).Repeat.Any();
            currentProject.Stub(x => x.WorkingDirectory).Return(DefaultDirectory).Repeat.Any();

            return currentProject;
        }
    }
}